package com.bosssoft.gateway.authentication.service.impl;

import com.bosssoft.gateway.authentication.pojo.dto.UserDTO;
import com.bosssoft.gateway.authentication.pojo.query.LoginQuery;
import com.bosssoft.gateway.authentication.service.AuthenticationService;
import com.bosssoft.gateway.authentication.service.LoginClient;
import common.annotation.ApiLog;
import common.cache.util.RedisUtils;
import common.exception.code.ThirdPartyApiErrorCode;
import common.exception.parse.ThirdPartyApiException;
import common.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @className: AuthenticationServiceImpl
 * @description: 实现认证业务
 * @author: lanyukai
 * @date: 2024/6/19 17:18
 * @since 1.0
 **/
@Service
@Slf4j
@Validated
@RefreshScope
public class AuthenticationServiceImpl implements AuthenticationService {

    /**
     * 通过登录客户端调用远程
     */
    @Autowired
    private LoginClient loginClient;
    /**
     * RedisTemplateConfig 中生成
     */
    @Resource(name = "tokenRedisTemplate")
    private RedisTemplate redisTemplate;

    /**
     * 默认设置10天的token有效期
     */
    private Long period = 864000L;

    /**
     * user的token的key
     */
    private static final String TOKEN_USER_ID_KEY = "user";

    /**
     * 通过DTP生成token
     * @param userDTO 用户的DTO信息
     * @return 用户token信息
     */
    public String generateToken(UserDTO userDTO){
        Map<String, Object> claims = new HashMap<>();
        claims.put("token", userDTO);
        return JwtUtil.generateToken(claims);
    }

    /**
     * 通过访问后端接口进行认证，返回认证结果
     * @author lanyukai
     * @date 2024/06/20 15:55
     * @param loginQuery 用户输入的登陆表单
     * @return 后端返回的认证结果
     */

    public UserDTO getUserFromBackend(LoginQuery loginQuery){
        return loginClient.login(loginQuery).getBody();
    }

    @Override
    @ApiLog
    public String doAuth(@Valid @NotNull LoginQuery loginQuery) {
        /*从远程获取用户DTO信息，并生成token*/
        UserDTO userDTO = getUserFromBackend(loginQuery);
        if(userDTO == null){
            throw new ThirdPartyApiException(ThirdPartyApiErrorCode.ACCESS_NOT_PASS, "无法通过认证，输入有误");
        }
        String token = generateToken(userDTO);
        /*将token存储到redis中*/
        redisTemplate.opsForValue().set(TOKEN_USER_ID_KEY + userDTO.getId(),
                token, period, TimeUnit.SECONDS);

        return token;
    }
}
